/**
 * @file    dev_pcf85163.c
 * @brief   外部设备驱动-RTC驱动
 * @author  Liuwei
 * @version 1.0.1
 * @date    2024-03-28
 * 
 * @copyright Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version   <th>Author   <th>Description
 * <tr><td>2024-03-28 <td>1.0.1     <td>Liuwei   <td>首次创建
 * </table>
 */

/* includes ------------------------------------------------------------------*/
#include "dev_pcf85163.h"
#include "drv_i2c_soft.h"
/* macro/define --------------------------------------------------------------*/
#define RTC_CMD_RD        (1)
#define RTC_CMD_WR        (0)
#define DEV_RTC_ADDR      (0xA2)
#define RTC_DRV_I2C       (DRV_I2C0)
/* typedef -------------------------------------------------------------------*/

/* local functions -----------------------------------------------------------*/
static uint8_t bcd_to_hex(uint8_t bcd_data);
static uint8_t hex_to_bcd(uint8_t hex_data);
/* static variables ----------------------------------------------------------*/
static uint8_t dev_rtc_set_reg(uint8_t addr ,uint8_t *buf,uint8_t len);
static uint8_t dev_rtc_read_reg(uint8_t addr ,uint8_t *buf,uint8_t len);
/* global variables ----------------------------------------------------------*/

/** ------------------------------------------------------------------------- *
  *                             Global function
 ** ------------------------------------------------------------------------- */
/**
 * @brief 设备RTC初始化
 */
uint8_t dev_pcf85163_init(rtc_data_type rtc_init)
{
	uint8_t res = 0;
	uint8_t data_buf[2] = {0};
	
    drv_i2c_soft_init(RTC_DRV_I2C);
	
	data_buf[0] = 0x00;
    res = dev_rtc_set_reg(PCF85163_CTL1 , data_buf , 1); 
	
    res = dev_rtc_read_reg(PCF85163_REG_SEC , data_buf , 1);
	if(TRUE == res)
	{
		if(data_buf[0] & 0x80) // 系统时钟未初始化
		{
			res = dev_pcf85163_set_date_time(rtc_init);
		}
	}
	
	return res;
}

/**
 * @brief 读取设备RTC日期和时间
 */
uint8_t dev_pcf85163_read_date_time(rtc_data_type *rtc_data)
{
	uint8_t data_buf[7] = {0};
	
	dev_rtc_read_reg(PCF85163_REG_SEC ,data_buf,7);
	
	if(data_buf[0] & 0x80)
	{
		data_buf[0] &= 0x7F;
		dev_rtc_set_reg(PCF85163_REG_SEC ,data_buf,1);
	}
	
	rtc_data->sec = bcd_to_hex(data_buf[0]& 0x7F) ;
	rtc_data->min = bcd_to_hex(data_buf[1]& 0x7F) ;
	rtc_data->hour = bcd_to_hex(data_buf[2] &0x3F);
	rtc_data->day = bcd_to_hex(data_buf[3]& 0x3F) ;
	rtc_data->week = bcd_to_hex(data_buf[4]& 0x07) + 1;
	rtc_data->month = bcd_to_hex(data_buf[5] & 0x1F);
	rtc_data->year = bcd_to_hex(data_buf[6]) + 2000;

    return TRUE;
}

/**
 * @brief 设置设备RTC日期和时间
 */
uint8_t dev_pcf85163_set_date_time(rtc_data_type set_val)
{
    uint8_t data_buf[7] = {0};
	uint8_t ret = 0;
	
	data_buf[0] = hex_to_bcd(set_val.sec);
	data_buf[1] = hex_to_bcd(set_val.min);
	data_buf[2] = hex_to_bcd(set_val.hour)|0x80;  /* 24Hour制 */
	data_buf[3] = hex_to_bcd(set_val.day);
	data_buf[4] = hex_to_bcd(set_val.week);
	data_buf[5] = hex_to_bcd(set_val.month);
	data_buf[6] = hex_to_bcd(set_val.year - 2000);
	
	ret = dev_rtc_set_reg(PCF85163_REG_SEC , data_buf , 7); 
	
	return ret;
}

/** ------------------------------------------------------------------------- *
  *                              Local function
 ** ------------------------------------------------------------------------- */
static uint8_t bcd_to_hex(uint8_t bcd_data)
{
    return (((bcd_data>>4)*10)+(bcd_data&0x0f));
}

static uint8_t hex_to_bcd(uint8_t hex_data)
{
    return (((hex_data/10)<<4) | (hex_data%10));
}

static uint8_t dev_rtc_set_reg(uint8_t addr ,uint8_t *buf,uint8_t len)
{
	uint8_t i = 0;
	drv_i2c_soft_start(RTC_DRV_I2C);
    drv_i2c_soft_write_byte(RTC_DRV_I2C , DEV_RTC_ADDR);
    if(FALSE == drv_i2c_soft_read_ack(RTC_DRV_I2C))
    {
        drv_i2c_soft_stop(RTC_DRV_I2C);
        return FALSE;
    }
    drv_i2c_soft_write_byte(RTC_DRV_I2C , addr);
	if(FALSE == drv_i2c_soft_read_ack(RTC_DRV_I2C))
    {
        drv_i2c_soft_stop(RTC_DRV_I2C);
        return FALSE;
    }
    for(i = 0;i < len; ++ i)
    {
        drv_i2c_soft_write_byte(RTC_DRV_I2C , buf[i]);
        if(FALSE == drv_i2c_soft_read_ack(RTC_DRV_I2C))
        {
            drv_i2c_soft_stop(RTC_DRV_I2C);
            return FALSE;
        }
    }

    drv_i2c_soft_stop(RTC_DRV_I2C);
    return TRUE;
}

static uint8_t dev_rtc_read_reg(uint8_t addr ,uint8_t *buf,uint8_t len)
{
	uint8_t i = 0;
	if(len == 0)
		return FALSE;
	
	drv_i2c_soft_start(RTC_DRV_I2C);
    drv_i2c_soft_write_byte(RTC_DRV_I2C , DEV_RTC_ADDR|RTC_CMD_WR);
    if(FALSE == drv_i2c_soft_read_ack(RTC_DRV_I2C))
    {
        drv_i2c_soft_stop(RTC_DRV_I2C);
        return FALSE;
    }
    drv_i2c_soft_write_byte(RTC_DRV_I2C , addr);
	if(FALSE == drv_i2c_soft_read_ack(RTC_DRV_I2C))
    {
        drv_i2c_soft_stop(RTC_DRV_I2C);
        return FALSE;
    }
	
	drv_i2c_soft_start(RTC_DRV_I2C);
	drv_i2c_soft_write_byte(RTC_DRV_I2C , DEV_RTC_ADDR |RTC_CMD_RD);
	
	if (FALSE == drv_i2c_soft_read_ack(RTC_DRV_I2C)) 
    { 
		drv_i2c_soft_stop(RTC_DRV_I2C);
		return FALSE;
	}
    for(i = 0;i < len; ++ i)
    {
        buf[i] = drv_i2c_soft_read_byte(RTC_DRV_I2C);
        if (i < len - 1)
        {
            drv_i2c_soft_write_ack(RTC_DRV_I2C); 
        } 
        else 
        {
            drv_i2c_soft_write_nack(RTC_DRV_I2C); 
        }
    }

    drv_i2c_soft_stop(RTC_DRV_I2C);
	
	return TRUE;
}

/********** Copyright (c) 2023 JBD-Energy Storage Technology Co. LTD *********/

